#include "xvideoui.h"
#include "ui_xvideoui.h"
#include <QFileDialog>
#include <QMessageBox>
#include "xvideothread.h"
#include "xsliderthread.h"
#include "xfilter.h"
#include "xaudio.h"

static bool pressSlider = false; //滑动条使用状态

static bool isExport = false; //非导出状态

static bool isColor = true; //RGB还是灰度图

static bool isMark = false; //是否添加水印（与视频融合和视频合并互斥）

static bool isBlend = false; //是否进行视频融合（与添加水印和视频合并互斥）

static bool isMerge = false; //是否进行视频合并（与添加水印和视频合并互斥）

XVideoUI::XVideoUI(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::XVideoUI)
{
    ui->setupUi(this);

    ui->src1video->setFixedSize(380, 280);
    ui->des->setFixedSize(380, 280);
    ui->src2video->setFixedSize(240, 160);

    this->setWindowFlags(Qt::FramelessWindowHint);
    //Qt不支持mat类型信号槽传参，要注册
    qRegisterMetaType<cv::Mat>("cv::Mat");
    //原视频
    connect(XVideoThread::getInstance(), &XVideoThread::sigViewImage1, ui->src1video, &XVideoWidget::do_setImage);
    //视频融合时，原视频2
    connect(XVideoThread::getInstance(), &XVideoThread::sigViewImage2, ui->src2video, &XVideoWidget::do_setImage);
    //滑动条
    connect(XSliderThread::getInstance(), &XSliderThread::sigSendPos, this, &XVideoUI::do_setPos);
    //输出视频
    connect(XVideoThread::getInstance(), &XVideoThread::sigViewDes, ui->des, &XVideoWidget::do_setImage);

    //导出视频结束
    connect(XVideoThread::getInstance(), &XVideoThread::sigSaveEnd, this, &XVideoUI::do_exportEnd);

    //析构时触发关闭线程
    connect(this, &XVideoUI::destroyed, [=](){
        XVideoThread::getInstance()->isExit = true;
        //停止线程
        XVideoThread::getInstance()->quit();
        //等待线程处理完手头工作
        XVideoThread::getInstance()->wait();
        XVideoThread::getInstance()->deleteLater();

        XSliderThread::getInstance()->isExit = true;
        //停止线程
        XSliderThread::getInstance()->quit();
        //等待线程处理完手头工作
        XSliderThread::getInstance()->wait();
        XSliderThread::getInstance()->deleteLater();
    });

    on_btnPlay_clicked(false); //默认暂停状态
}

XVideoUI::~XVideoUI()
{
    delete ui;
}

void XVideoUI::do_setPos(double pos)
{
    //改变滑动条位置
    ui->sliderPlay->setValue(pos * 1000);
}

void XVideoUI::on_btnOpen_clicked()
{
    QString filePath = QFileDialog::getOpenFileName(this, "请选择视频文件");
    if (filePath.isEmpty()) {
        return;
    }
    if (!XVideoThread::getInstance()->open(filePath.toStdString())){
        QMessageBox::information(this, "error", filePath+"open failed");
    }
    XVideoThread::getInstance()->start();
    XSliderThread::getInstance()->start();
    //startTimer(40); //刷新滑动条
}


void XVideoUI::on_sliderPlay_sliderPressed()
{
    pressSlider = true;
    //关闭两个子线程，不然很卡
    XSliderThread::getInstance()->isExit = true;
    XVideoThread::getInstance()->isExit = true;
}


void XVideoUI::on_sliderPlay_sliderReleased()
{
    pressSlider = false;
    XSliderThread::getInstance()->isExit = false;
    XSliderThread::getInstance()->start();

    XVideoThread::getInstance()->isExit = false;
    XVideoThread::getInstance()->start();
}


void XVideoUI::on_sliderPlay_sliderMoved(int position)
{
    XVideoThread::getInstance()->seek((double)position / 1000.0);
}


void XVideoUI::on_sliderContrast_valueChanged(int value)
{

}


void XVideoUI::on_sliderBrightness_valueChanged(int value)
{

}


void XVideoUI::on_btnSet_clicked()
{
    XFilter::getInstance()->fClear();
    isColor = true;

    //视频图像裁剪（图像金字塔，调整视频尺寸都不能做了）
    bool isClip = false;
    double cX = ui->spinBoxClipX->value();
    double cY = ui->spinBoxClipY->value();
    double cW = ui->spinBoxClipW->value();
    double cH = ui->spinBoxClipH->value();
    if (cX + cY + cW + cH > 0.0010) {
        isClip = true;
        XFilter::getInstance()->fAdd(XTask
            {XTASK_CLIP, {cX, cY, cW, cH}}
        );
        double w = XVideoThread::getInstance()->width;
        double h = XVideoThread::getInstance()->height;
        XFilter::getInstance()->fAdd(XTask
            {XTASK_RESIZE, {w, h}}
        );
    }

    //图像金字塔
    bool isPy = false;
    int down = ui->spinBoxPyDown->value();
    int up = ui->spinBoxPyUp->value();
    if (up > 0) {
        isPy = true;
        XFilter::getInstance()->fAdd(XTask
                                     {XTASK_PYUP, {(double)up}}
                                     );
        int w = XVideoThread::getInstance()->width;
        int h = XVideoThread::getInstance()->height;
        for (int i = 0; i < up; ++i) {
            w = w * 2;
            h = h * 2;
        }
        ui->spinBoxW->setValue(w);
        ui->spinBoxH->setValue(h);
    }
    if (down > 0) {
        isPy = true;
        XFilter::getInstance()->fAdd(XTask
        {XTASK_PYDOWN, {(double)down}}
        );
        int w = XVideoThread::getInstance()->width;
        int h = XVideoThread::getInstance()->height;
        for (int i = 0; i < up; ++i) {
            w = w / 2;
            h = h / 2;
        }
        ui->spinBoxW->setValue(w);
        ui->spinBoxH->setValue(h);
    }


    //图像旋转 0 1 2 3 - 0 90 180 270
    if (ui->cBoxRotate->currentIndex() == 1) {
        XFilter::getInstance()->fAdd(XTask{XTASK_ROTATE90});
    }
    else if (ui->cBoxRotate->currentIndex() == 2) {
        XFilter::getInstance()->fAdd(XTask{XTASK_ROTATE180});
    }
    else if (ui->cBoxRotate->currentIndex() == 3) {
        XFilter::getInstance()->fAdd(XTask{XTASK_ROTATE270});
    }

    //调整视频尺寸（与图像金字塔只能触发一个）
    double w = ui->spinBoxW->value();
    double h = ui->spinBoxH->value();
    if (!isMerge && !isClip && !isPy && ui->spinBoxW->value() > 0 && ui->spinBoxH->value() > 0) {
        XFilter::getInstance()->fAdd(XTask
        {XTASK_RESIZE, {w, h}}
        );
    }


    //对比度和亮度
    if (ui->sliderBrightness->value() > 0 || ui->sliderContrast->value() > 1) {
        XFilter::getInstance()->fAdd(XTask
            {XTASK_GAIN, {(double)ui->sliderBrightness->value(), (double)ui->sliderContrast->value() / 33}}
            );
    }

    //灰度图
    if (ui->cBoxColor->currentIndex() == 1) {
        XFilter::getInstance()->fAdd(XTask
            {XTASK_GRAY}
        );
        isColor = false;
    }

    //图像镜像
    if (ui->cBoxFlip->currentIndex() == 1) {
        XFilter::getInstance()->fAdd(XTask{XTASK_FLIPX});
    }
    else if (ui->cBoxFlip->currentIndex() == 2) {
        XFilter::getInstance()->fAdd(XTask{XTASK_FLIPY});
    }
    else if (ui->cBoxFlip->currentIndex() == 3) {
        XFilter::getInstance()->fAdd(XTask{XTASK_FLIPXY});
    }

    //添加水印
    if (isMark) {
        double x = ui->spinBoxMarkX->value();
        double y = ui->spinBoxMarkY->value();
        double a = ui->spinBoxMarkA->value();
        XFilter::getInstance()->fAdd(XTask
            {XTASK_MARK, {x, y, a}}
        );
    }

    //视频融合
    if (isBlend) {
        double a = ui->spinBoxBlendA->value();
        XFilter::getInstance()->fAdd(XTask
            {XTASK_BLEND, {a}}
        );
    }

    //视频合并
    if (isMerge) {
        double h1 = XVideoThread::getInstance()->height;
        double h2 = XVideoThread::getInstance()->height2;
        int w = XVideoThread::getInstance()->width2 * (h2 / h1) ;
        XFilter::getInstance()->fAdd(XTask
            {XTASK_MERGE}
        );
        ui->spinBoxW->setValue(XVideoThread::getInstance()->width + w);
        ui->spinBoxH->setValue(h1);
    }
}


void XVideoUI::on_btnExport_clicked()
{
    if (isExport) { //导出状态下点击按钮，停止导出
        XVideoThread::getInstance()->stopSave();
        isExport = false;
        ui->btnExport->setText("导出");
        return;
    }
    QString filePath = QFileDialog::getSaveFileName(this, "保存视频", "save.mp4");
    if (filePath.isEmpty()) {
        return;
    }
    //可能改变宽高
    int w = ui->spinBoxW->value();
    int h = ui->spinBoxH->value();
    if (XVideoThread::getInstance()->startSave(filePath.toStdString(), w, h, isColor)) {
        //导出成功
        isExport = true;
        ui->btnExport->setText("停止导出");
    }
}

void XVideoUI::do_exportEnd()
{
    isExport = false;
    ui->btnExport->setText("导出");

    //处理音频
    string src = XVideoThread::getInstance()->src1File;
    string des = XVideoThread::getInstance()->desFile;
    int beginS = 0; //开始位置
    int t = 0;  //视频时长
    beginS = XVideoThread::getInstance()->totalMs * ((double)ui->sliderLeft->value() / 1000.);
    //结束位置
    int endS = XVideoThread::getInstance()->totalMs * ((double)ui->sliderRight->value() / 1000.);
    t = endS - beginS;
    //获取原视频src音乐
    XAudio::getInstance()->exportAudio(src, src + ".mp3", beginS, t);
    //输出无音乐视频与音乐合并到des
    string tmp = des + ".mp4";
    QFile::remove(tmp.c_str());
    QFile::rename(des.c_str(), tmp.c_str());
    XAudio::getInstance()->mergeAudio(tmp, src + ".mp3", des);
    //删除音乐和无音乐视频
    QFile::remove((src + ".mp3").c_str());
    QFile::remove(tmp.c_str());
}


void XVideoUI::on_btnPlay_clicked(bool checked)
{
    if (checked) {
        //变为播放状态
        ui->btnPlay->setText("pause");
        XVideoThread::getInstance()->play();
    }
    else {
        //变为暂停状态
        ui->btnPlay->setText("play");
        XVideoThread::getInstance()->pause();
    }
}


void XVideoUI::on_btnMark_clicked()
{
    isMark = false;
    isBlend = false;
    isMerge = false;
    QString filePath = QFileDialog::getOpenFileName(this, "请选择水印图片");
    if (filePath.isEmpty()) {
        return;
    }
    cv::Mat mark = cv::imread(filePath.toStdString());
    if (mark.empty()) {
        return;
    }
    XVideoThread::getInstance()->setMark(mark);
    isMark = true;
}


void XVideoUI::on_btnBlend_clicked()
{
    isMark = false;
    isBlend = false;
    isMerge = false;
    QString filePath = QFileDialog::getOpenFileName(this, "请选择想融合的视频");
    if (filePath.isEmpty()) {
        return;
    }
    isBlend = XVideoThread::getInstance()->open2(filePath.toStdString());
}


void XVideoUI::on_btnMerge_clicked()
{
    isMark = false;
    isBlend = false;
    isMerge = false;
    QString filePath = QFileDialog::getOpenFileName(this, "请选择想合并的视频");
    if (filePath.isEmpty()) {
        return;
    }
    isMerge = XVideoThread::getInstance()->open2(filePath.toStdString());
}


void XVideoUI::on_sliderLeft_sliderPressed()
{
    pressSlider = true;
    //关闭两个子线程，不然很卡
    XSliderThread::getInstance()->isExit = true;
    XVideoThread::getInstance()->isExit = true;
}


void XVideoUI::on_sliderLeft_sliderReleased()
{
    pressSlider = false;
    XSliderThread::getInstance()->isExit = false;
    XSliderThread::getInstance()->start();

    XVideoThread::getInstance()->isExit = false;
    XVideoThread::getInstance()->start();
}

void XVideoUI::on_sliderLeft_sliderMoved(int position)
{
    XVideoThread::getInstance()->setBegin((double)position / 1000.0);
  //  do_setPos(position); //视频滑动条跟着左侧滑动条移动(bug)
    XVideoThread::getInstance()->seek((double)position / 1000.0);
}


void XVideoUI::on_sliderRight_sliderPressed()
{
    pressSlider = true;
    //关闭两个子线程，不然很卡
    XSliderThread::getInstance()->isExit = true;
    XVideoThread::getInstance()->isExit = true;
}


void XVideoUI::on_sliderRight_sliderReleased()
{
    pressSlider = false;
    XSliderThread::getInstance()->isExit = false;
    XSliderThread::getInstance()->start();

    XVideoThread::getInstance()->isExit = false;
    XVideoThread::getInstance()->start();
}

void XVideoUI::on_sliderRight_sliderMoved(int position)
{
    XVideoThread::getInstance()->setEnd((double)position / 1000.0);
}
